<template>
    <div class="card" style="height: 93vh">
      <div  class="font-semibold text-xl mb-4">定时任务</div>
        <DataTable :value="data" paginator :rows="10" dataKey="id" :loading="dataLoading" scrollable
                   scrollHeight="50vh">
            <template #header>
                <div class="flex justify-between">
                    <div>
                        <Button class="mr-2" type="button" icon="pi pi-plus" label="新建" @click="showCreate"/>
                        <Button type="button" icon="pi pi-file" severity="secondary" label="日志"
                                @click="() => router.push({name: 'TaskHistories', query: {}})"/>
                    </div>
                    <IconField iconPosition="left">
                        <InputIcon>
                            <i class="pi pi-search"/>
                        </InputIcon>
                        <InputText placeholder="任务名称搜索"/>
                    </IconField>
                </div>
            </template>
            <Column field="name" header="名称"></Column>
            <Column field="script_name" header="脚本"></Column>
            <Column field="cron" header="cron"></Column>
            <Column field="status" header="状态">
                <template #body="slotProps">
                    <Tag v-if="slotProps.data.enable === false" severity="warn" value="禁用"></Tag>
                    <Tag severity="success" value="成功" v-else-if="slotProps.data.last_status === 0"></Tag>
                    <Tag v-else-if="slotProps.data.last_status === 1" severity="danger" value="失败"></Tag>
                    <Tag v-else severity="info" value="等待"></Tag>
                </template>
            </Column>
            <Column field="args" header="参数"></Column>
            <Column field="recount" header="重试次数"></Column>
            <Column field="next_time" header="下次执行时间">
                <template #body="slotProps">
                    {{ formatDate(slotProps.data.next_time) }}
                </template>
            </Column>
            <Column field="history" header="日志">
                <template #body="slotProps">
                    <a class="cursor-pointer"
                       @click="() => router.push({name: 'TaskHistories', query: {task_id: slotProps.data.id}})">查看</a>
                </template>
            </Column>
            <Column field="username" header="创建者"></Column>
            <Column field="action" header="操作">
                <template #body="slotProps">
                    <i class="pi pi-pencil" @click="() => showEditor(slotProps.data)"></i>
                    <i class="pi pi-trash ml-3" @click="() => onRemove(slotProps.data.id)"></i>
                </template>
            </Column>
        </DataTable>
    </div>

    <Dialog
        modal
        width="40%"
        :header=" visible.editorId ? '编辑任务' : '创建任务'"
        v-model:visible="visible.createModal"
        :confirmLoading="loading.create"

    >
        <form @submit.prevent="onSubmit">
            <div class="mt-4 flex items-center gap-4">
                <label for="name" class="text-sm font-semibold text-right w-32">任务名称</label>
                <div class="flex-1">
                    <InputText id="name" v-model="name" class="w-full" autocomplete="off"/>
                    <small class="text-red-500">{{ errors.name }}</small>
                </div>
            </div>

            <div class="mt-4 flex items-center gap-4">
                <label for="script" class="text-sm font-semibold text-right w-32">脚本</label>
                <div class="flex-1">
                    <Dropdown v-model="script" :options="scriptData" optionLabel="name" optionValue="code"
                              placeholder="选择一个脚本" class="w-full md:w-56"/>
                    <small class="text-red-500">{{ errors.script }}</small>
                </div>
            </div>

            <div class="mt-4 flex items-center gap-4">
                <label class="text-sm font-semibold text-right w-32">CRON表达式</label>
                <div class="flex space-x-2">
                    <InputText v-model="minute" class="text-center w-14"/>
                    <span>分</span>
                    <InputText v-model="hour" class="text-center w-14"/>
                    <span>时</span>
                    <InputText v-model="day" class="text-center w-14"/>
                    <span>日</span>
                    <InputText v-model="month" class="text-center w-14"/>
                    <span>月</span>
                    <InputText v-model="week" class="text-center w-14"/>
                    <span>周</span>
                </div>
                <small v-if="errors.minute || errors.hour || errors.day || errors.month || errors.week"
                       class="text-red-500">CRON表达式不完整</small>
            </div>

            <div class="mt-4 flex items-center gap-4">
                <label class="text-sm font-semibold text-right w-32">随机延迟</label>
                <div>
                    <InputNumber v-model="delay_a" class="text-center"/>
                    <span>到</span>
                    <InputNumber v-model="delay_b" class="text-center"/>
                    <span>秒</span>
                </div>
                <small v-if="errors.delay_a || errors.delay_b" class="text-red-500">{{ errors.delay_a }}</small>
            </div>

            <div class="mt-4 flex items-center gap-4">
                <label class="text-sm font-semibold text-right w-32">失败重试次数</label>
                <div class="flex-1">
                    <InputNumber id="recount" v-model="recount" autocomplete="off"/>
                    <small class="text-red-500">{{ errors.recount }}</small>
                </div>
            </div>

            <div class="mt-4 flex items-center gap-4">
                <label class="text-sm font-semibold text-right w-32">启用</label>
                <div>
                    <ToggleSwitch id="enable" v-model="enable"/>
                    <small class="text-red-500">{{ errors.enable }}</small>
                </div>
            </div>

            <div class="mt-6 flex justify-end gap-2">
                <Button type="button" label="取消" severity="secondary" @click="visible.createModal = false"></Button>
                <Button type="submit" label="保存"></Button>
            </div>
        </form>

    </Dialog>

    <Dialog v-model:visible="visible.setScriptArgs" header="设置脚本参数" :style="{ width: '70rem' }">
        <form @submit.prevent='onSubmit'>
            <div class="formgroup-inline align-items-center">
                <div v-for="(item, index) in formState.args" class="field flex align-items-center">
                    <label class="font-semibold">{{ item.name }}</label>
                    <div class="flex flex-column">
                        <InputText v-if="item.type === 'one_str'" :id="item.id" v-model="item.value"
                                   autocomplete="off"/>

                        <Textarea v-else-if="item.type === 'multi_str'" :id="item.id" v-model="item.value" rows="5"
                                  cols="50"
                                  autocomplete="off"/>

                        <div v-else-if="item.type === 'bool'" class="flex flex-wrap gap-3">
                            <div class="flex align-items-center">
                                <RadioButton v-model="item.value" inputId="ingredient1" name="pizza"
                                             :value="true" :id="item.id"/>
                                <label for="ingredient1" class="ml-2">是</label>
                            </div>
                            <div class="flex align-items-center">
                                <RadioButton v-model="item.value" inputId="ingredient2" name="pizza" :value="false"
                                             :id="item.id"/>
                                <label for="ingredient1" class="ml-2">否</label>
                            </div>
                        </div>

                        <div v-else-if="item.type === 'enums'" class="flex flex-wrap gap-3">
                            <Select class='w-8rem' v-model="item.value" :options="item.enums" aria-labelledby="basic"/>
                        </div>
                        <div v-else-if="item.type === 'password'" class="flex flex-wrap gap-3">
                            <Password v-model="item.value" :feedback="false"/>
                        </div>
                        <div v-else-if="item.type === 'number'" class="flex flex-wrap gap-3">
                            <InputNumber v-model="item.value"/>
                        </div>
                        <small class="p-error">
                            {{ errors[item.id] }}
                        </small>
                    </div>
                </div>
            </div>

            <div style="width:100%;display: flex; justify-content: space-between;" class='mb-3'>
                <Button @click="copyContent" severity="secondary">复制</Button>
                <div>
                    <Button type="submit" label="执行" :loading="debugLoading"/>
                    <Button key="back" danger @click="() => discontinue()" severity="secondary" class='ml-2'>终止
                    </Button>
                </div>
            </div>
        </form>
        <!--      <div class="p-3" style="background-color: red">-->
        <div ref="xtermContainer"/>
        <!--      </div>-->
    </Dialog>

    <ConfirmDialog></ConfirmDialog>
</template>

<script setup>

import {useRequest} from "ahooks-vue";
import {ApiCreate, ApiDelete, ApiList, ApiUpdate} from "@/api/scheduler.js";
import {h, reactive, ref} from "vue";
import {ApiToolkitList} from "@/api/toolkit.js";
import IconField from 'primevue/iconfield';
import InputIcon from 'primevue/inputicon';
import ConfirmDialog from 'primevue/confirmdialog';
import router from "@/router.js";
import * as yup from "yup";
import {useForm} from "vee-validate";
import {useToast} from "primevue/usetoast";
import {useConfirm} from "primevue/useconfirm";
import {formatDate} from "@/utils/format.js";
import InputGroup from 'primevue/inputgroup';
import InputGroupAddon from 'primevue/inputgroupaddon';
import ToggleSwitch from 'primevue/toggleswitch';


const confirm = useConfirm();
const toast = useToast();


const visible = reactive({
    createModal: false,
    setScriptArgs: false,
    editorId: -1
})
const loading = reactive({
    create: false
})
const formState = reactive({
    name: '',
    script_id: '',
    cron: '',
    re_count: 0,
    desc: '',
    args: []
});
const data = ref([])
const scriptData = ref([])
const scriptArgs = ref({})

const {loading: dataLoading, run, refresh} = useRequest(ApiList, {
    defaultParams: [{
        page: 1,
        page_size: 10
    }],
    onSuccess: (e) => {
        data.value = e.data.list
    }
})

const {loading: scriptLoading, refresh: scriptRefresh} = useRequest(ApiToolkitList, {
    manual: true,
    defaultParams: [{
        page: 1,
        page_size: 999999
    }],
    onSuccess: (e) => {
        e.data.list.forEach(item => {
            scriptData.value.push({
                name: item['name'],
                code: item['id']
            })
            scriptArgs.value[item['id']] = item.args
        })
    }
})

const scriptSelectChange = (scriptId) => {

    formState.args = scriptArgs.value[scriptId]
}

const filterOption = (input, option) => {
    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
};
const showCreate = async () => {
    visible.editorId = -1
    scriptRefresh()
    visible.createModal = true


}


const onRemove = (id) => {
    confirm.require({
        message: '确认要删除这个任务吗？',
        header: '删除提示',
        icon: 'pi pi-exclamation-triangle',
        rejectProps: {
            label: '取消',
            severity: 'secondary',
            outlined: true
        },
        acceptProps: {
            label: '删除'
        },
        accept: async () => {
            const result = await ApiDelete(id)
            if (result.code === 0) {
                toast.add({severity: 'success', summary: '成功', detail: result.msg, life: 3000});
                await refresh()
            } else {
                toast.add({severity: 'error', summary: '失败', detail: result.msg, life: 3000});
            }

        }
    });

    // modal.confirm({
    //   title: '删除提示',
    //   icon: h(ExclamationCircleOutlined),
    //   content: '确认要删除这个任务吗？',
    //   okText: '删除',
    //   okType: 'danger',
    //   cancelText: '取消',
    //   onOk() {
    //     remove(id)
    //   },
    // });
};

const remove = async (id) => {

}

const showEditor = async (data) => {
    visible.editorId = data.id
    visible.createModal = true

    await scriptRefresh()
    const cron = data.cron.split(' ')
    if (data.delay !== undefined && data.delay !== null) {
        const delay = data.delay.split('-')
        delay_a.value = delay[0]
        delay_b.value = delay[1]
    } else {
        delay_a.value = 0
        delay_b.value = 0
    }
    name.value = data.name
    script.value = data.script
    minute.value = cron[0]
    hour.value = cron[1]
    day.value = cron[2]
    month.value = cron[3]
    week.value = cron[4]
    recount.value = data.recount
    args.value = data.args
    desc.value = data.desc
    enable.value = data.enable

}

//before other day
const dateTestBeforeOtherDay = function (field) {
    return function (value, context) {
        return false
    }
}

let schema = yup.object().shape({
    name: yup.string().max(20, '字符长度过多').required('请输入任务名称'),
    script: yup.string().max(20, '字符长度过多').required('请选择脚本'),
    minute: yup.string().default('sdf').max(20, '字符长度过多').required('CRON表达式不完整'),
    hour: yup.string().max(20, '字符长度过多').required('CRON表达式不完整'),
    day: yup.string().max(20, '字符长度过多').required('CRON表达式不完整'),
    month: yup.string().max(20, '字符长度过多').required('CRON表达式不完整'),
    week: yup.string().max(20, '字符长度过多').required('CRON表达式不完整'),
    delay_a: yup.number().max(3600).default(0).test('delay_a', '输入错误', (value, context) => {
        if (value > delay_b.value) {
            return false
        }
        return true
    }),
    delay_b: yup.number().max(3600).default(0),
    enable: yup.bool().required('请选择启动状态'),
});
const {defineField, handleSubmit, errors} = useForm({
    validationSchema: schema,
    initialValues: {
        minute: '*',
        hour: '*',
        day: '*',
        month: '*',
        week: '*',
        delay_a: 0,
        delay_b: 0,
        enable: true
    }
});
const [name] = defineField('name');
const [script] = defineField('script');
const [minute] = defineField('minute');
const [hour] = defineField('hour');
const [day] = defineField('day');
const [month] = defineField('month');
const [week] = defineField('week');
const [delay_a] = defineField('delay_a');
const [delay_b] = defineField('delay_b');
const [recount] = defineField('recount');
const [enable] = defineField('enable');
const [args] = defineField('args');
const [desc] = defineField('desc');

const onSubmit = handleSubmit(async (values) => {
    const params = {...values}

    const cron = params.minute + " " + params.hour + " " + params.day + " " + params.month + " " + params.week
    const delay = params.delay_a + '-' + params.delay_b
    if (visible.editorId > -1) {
        const result = await ApiUpdate({
            id: visible.editorId, name: params.name, script: params.script,
            recount: params.recount, cron: cron, delay: delay, enable: params.enable
        })
        if (result.code === 0) {
            toast.add({severity: 'success', summary: '成功', detail: '更新成功', life: 3000});
            visible.createModal = false
            await refresh()
        } else {
            toast.add({severity: 'danger', summary: '错误', detail: '更新失败', life: 3000});
        }
    } else {
        const result = await ApiCreate({
            name: params.name,
            script: params.script,
            recount: params.recount,
            cron: cron,
            delay: delay,
            enable: params.enable
        })
        if (result.code === 0) {
            toast.add({severity: 'success', summary: '成功', detail: result.msg, life: 3000});
            visible.createModal = false
            await refresh()
        } else {
            toast.add({severity: 'danger', summary: '错误', detail: result.msg, life: 3000});
        }
    }

})

</script>

<style scoped>
.toolbar {
    height: 48px;
    display: flex;
    justify-content: space-between;
}

.toolbar-left {
    font-size: 16px;
}

</style>
